
#include "Self_Define_Functions.h"


/*
*
*
*
*
*
*
*
*
*
*
*
*
*/


// create new object of class for different functions
Benchmarks* generateFuncObj(int funcID)
{
	Benchmarks *fp;
	// run each of specified function in "configure.ini"
	if (funcID==1){
		fp = new F1();
	}else if (funcID==2){
		fp = new F2();
	}else if (funcID==3){
		fp = new F3();
	}else if (funcID==4){
		fp = new F4();
	}else if (funcID==5){
		fp = new F5();
	}else if (funcID==6){
		fp = new F6();
	}else if (funcID==7){
		fp = new F7();
	}else if (funcID==8){
		fp = new F8();
	}else if (funcID==9){
		fp = new F9();
	}else if (funcID==10){
		fp = new F10();
	}else if (funcID==11){
		fp = new F11();
	}else if (funcID==12){
		fp = new F12();
	}else if (funcID==13){
		fp = new F13();
	}else if (funcID==14){
		fp = new F14();
	}else if (funcID==15){
		fp = new F15();
	}else if (funcID==16){
		fp = new F16();
	}else if (funcID==17){
		fp = new F17();
	}else if (funcID==18){
		fp = new F18();
	}else if (funcID==19){
		fp = new F19();
	}else if (funcID==20){
		fp = new F20();
	}else{
		cerr<<"Fail to locate Specified Function Index"<<endl;
		exit(-1);
	}
	return fp;
}



void Fitness( double &results, double *particle,  int &FV, Benchmarks* fp )
{
    results =  fp->compute( particle );
    FV++;
}


//Fitness Computation
void Fitness_Computation( double *results, double **population, int &gbest, int num, int dim, int &FV, Benchmarks* fp )
{// num is the population size and dim is the size of dimensions
    int i;
    double best = results[0] = fp->compute( population[0] );
    gbest = 0;
    for( i = 1; i < num; ++i )
    {
        results[i] = fp->compute( population[i]);

        if( results[i] < best )
        {
            best = results[i];
            gbest = i;

        }
    }

    FV += num;
}



void Random_Diff_Number( int *base, int base_num, int NP, int *selected_num, int num )
{
    boost::mt19937 generator(time(0)*rand());
    boost::uniform_int<> uniform_int_NP( 0, NP-1 );
    boost::variate_generator< boost::mt19937&, boost::uniform_int<> > random_int_NP( generator, uniform_int_NP );

    bool flag = true;

    int i,j;
    int temp;



    int *temp_res = new int[num+base_num];
    for( i = 0; i < base_num; ++i )
        temp_res[i] = base[i];



    for( i = 0; i < num; ++i )
    {

        while(1)
        {
            temp = random_int_NP();
            flag = true;

            for( j = 0; j < i+base_num; ++j)
            {
                if( temp == temp_res[j] )
                {
                    flag = false;
                    break;

                }

            }
            if( flag )
            {
                temp_res[base_num+i] = selected_num[i] = temp;
                break;
            }

        }
    }

    delete []temp_res;
}

void Weighted_Global_Mean_Position( double **population, double * population_result, double *global_mean_position, int pop_size, int dim )
{
    int i, j;
    double sum = 0;

    for( i = 0; i < pop_size; ++i )
        sum += population_result[i];

    for( i = 0 ; i < dim; ++i )
    {
        global_mean_position[i] = 0;

        for( j = 0; j < pop_size; ++j )
            global_mean_position[i]+=  ( population_result[j]  / sum ) * population[j][i];

    }
}


void Update_Base_Set( double *result, int *winner, int winner_size, int *loser, int loser_size, int *base_set, int &base_size )
{
    int i;

//    double worst_winner;
//    worst_winner = Get_Worst_Winner( result, winner, winner_size );
    for( i = 0; i < winner_size; ++i )
    {
        base_set[i] = winner[i];
    }

    base_size = winner_size;

//    for( i = 0; i < loser_size; ++i )
//    {
//        if( result[loser[i]] < worst_winner )
//            base_set[base_size++] = loser[i];
//
//    }
}

double Compute_Relative_Performance( double pre_result, double current_result )
{
    if(pre_result < 1e-100 )
        return 1;
    else
        return abs( current_result - pre_result ) / abs( pre_result );
}

void Compute_Probablity( double *record, double *prob, int num )
{
    int i;
    double sum = 0;
    for( i = 0; i < num; ++i )
    {
        prob[i] = exp(7*record[i]);
        sum += prob[i];
    }

    for( i = 0; i < num; ++i )
    {
        prob[i] /= sum;

    }

    for( i = 1; i < num; ++i )
    {
        prob[i] += prob[i-1] ;

    }


}

int Select_Group_Size (  double* group_prob, int num )
{

    boost::mt19937 gen(time(0)*rand());
    boost::uniform_real<> unif( 0,1 );
    boost::variate_generator< boost::mt19937&, boost::uniform_real<> > unif_dist( gen, unif );

    double temp = unif_dist();

    int i ;
    if( temp >=0 && temp <=group_prob[0] )
        return 0;
    else
    {
        for( i = 1; i < num; ++i )
            if( temp >group_prob[i-1] && temp <=group_prob[i] )
            {
                break;
            }

        return i;

    }

}













